Analyze Planner Value

Import Data

mt_plan_v_tilde <- read.csv('C:/Users/fan/Documents/Dropbox (UH-ECON)/PrjNygaardSorensenWang/Output/snwx_v_planner_small.csv', header=FALSE)
ar_st_varnames <- c('age', 'marital', 'kids', 'checks', 'ymin', 'ymax', 'mass', 'survive', 'vtilde', 'ctilde')
tb_plan_v_tilde <- as_tibble(mt_plan_v_tilde) %>%
  rename_all(~c(ar_st_varnames)) %>%
  rowid_to_column(var = "id") %>%
  filter(vtilde != 0)

# Column 1: Age (in year before COVID)
# Column 2: Marital status (0 if not married; 1 if married)
# Column 3: Nr of kids (0, 1, ..., 5) where 5 means 5 or more
# Column 4: Number of welfare checks (here either equal to 0 or 1)
# Column 5 and column 6 give income range
# So the individual's income is at least as large as the value in column 5 but strictly less than the value in column 6
# Column 7: Population weight Of that particular group (in the stationary distribution)
# Column 8: Survival probability of that particular age (since the planner knows that some of the individuals will die before next period, so wasn't sure how you wanted me to include that. I did not already include it in V^tilde)
# Column 9: Value of planner as in the slides (with the exception that I didn't multiply by the survival probability

Generate A and alpha file version

tb_plan_v_tilde_a_alpha <- tb_plan_v_tilde %>% 
  arrange(age, marital, kids, ymin, checks, vtilde, ctilde) %>%
  group_by(age, marital, kids, ymin) %>%
  mutate(vtilde_lead = lead(vtilde), 
         ctilde_lead = lead(ctilde)) %>%
  filter(checks != max(tb_plan_v_tilde$checks)) %>%
  rename(V_A_i = vtilde, C_A_i = ctilde) %>%
  mutate(V_alpha_i = vtilde_lead - V_A_i, 
         C_alpha_i = ctilde_lead - C_A_i) %>%
  mutate(checks = checks + 1) %>%
  ungroup()
print(tb_plan_v_tilde_a_alpha)

Summarize All Columns Unconditional

REconTools::ff_summ_percentiles(tb_plan_v_tilde_a_alpha, bl_statsasrows = FALSE)
attributes are not identical across measure variables;
they will be dropped

Summarize All Columns by Checks

Will summarize all varaibles by 4 different check amounts, the four check increments are (each is worth 200 dollars):

# Unique Checks:
ar_checks <- sort(unique(tb_plan_v_tilde_a_alpha %>% pull(checks)))
ar_checks_4 <- ar_checks[seq(1, length(ar_checks), length.out=4)]
mt_checks_4 <- ar_checks_4
dim(mt_checks_4) <- c(length(ar_checks_4), 1)
mt_checks*200
      [,1]
[1,]   200
[2,]  3400
[3,]  6600
[4,] 10000

Now summarize by these check amounts:

# Summarize all Variables Each Check:
ls_stats_by_checks = suppressWarnings(
  apply(mt_checks_4, 1,
        function(row) {
          fl_check = row[1]
          REconTools::ff_summ_percentiles(
            tb_plan_v_tilde_a_alpha %>% 
              filter(checks == fl_check), 
            bl_statsasrows = FALSE)
        }))

# Print Stats
print(ls_stats_by_checks)
[[1]]

[[2]]

[[3]]

[[4]]
NA

Joint distribution of A and alpha by Check (Show Only for Four Checks)

Joint Distribution of Effects on Consumption
# Generate Gap Variable
dft_graph <- tb_plan_v_tilde_a_alpha %>%
  filter(checks %in% ar_checks_4) %>%
  mutate(marital = as.factor(marital),
         kids = as.factor(kids))

# Titling
st_title <- sprintf("2020 Consumption without Binary Check and Marginal Effects of Checks")
title_line1 <- sprintf("Each circle (cross) represents an Age/Marriage/Child/Income/Check Type")
title <- expression('The joint distribution of'~A[i]~'and'~alpha[i]~', Checks, SNW 2020')
caption <- paste0('Life Cycle Simulation.')
# Labels
st_x_label <- expression('Cons 2020 without the Next Increment of Checks')
st_y_label <- expression('Marginal C from An Additional Check')

# Binary Marginal Effects and Prediction without Binary
plt_A_alpha <- dft_graph %>% ggplot(aes(x=C_A_i)) +
      geom_point(aes(y=C_alpha_i,
                     color=factor(checks))) +
      geom_abline(intercept = 0, slope = 1) + # 45 degree line
      labs(title = st_title,
           subtitle = paste0(title_line1),
           x = st_x_label,
           y = st_y_label,
           caption = caption) 
# Labeling
plt_A_alpha$labels$color <- "checks"

print(plt_A_alpha)

Joint Distribution of Effects on Value
# Generate Gap Variable
dft_graph <- tb_plan_v_tilde_a_alpha %>%
  filter(checks %in% ar_checks_4) %>%
  mutate(marital = as.factor(marital),
         kids = as.factor(kids))

# Titling
st_title <- sprintf("Value (Life-Time) without Binary Check and Marginal Effects of Checks")
title_line1 <- sprintf("Each circle (cross) represents an Age/Marriage/Child/Income/Check Type")
title <- expression('The joint distribution of'~A[i]~'and'~alpha[i]~', Checks, SNW 2020')
caption <- paste0('Life Cycle Simulation.')
# Labels
st_x_label <- expression('Life-time Utility without the Next Increment of Checks')
st_y_label <- expression('Marginal V from An Additional Check')

# Binary Marginal Effects and Prediction without Binary
plt_A_alpha <- dft_graph %>% ggplot(aes(x=V_A_i)) +
      geom_point(aes(y=V_alpha_i,
                     color=factor(checks))) +
      geom_abline(intercept = 0, slope = 1) + # 45 degree line
      labs(title = st_title,
           subtitle = paste0(title_line1),
           x = st_x_label,
           y = st_y_label,
           caption = caption) 
# Labeling
plt_A_alpha$labels$color <- "checks"

print(plt_A_alpha)

Joint distribution of A and alpha by Income Groups

# Select 4 Y groups Levels
ar_ymin <- sort(unique(tb_plan_v_tilde_a_alpha %>% pull(ymin)))
ar_ymin <- ar_ymin[seq(1, length(ar_ymin), length.out=4)]

dft_graph_subset <- dft_graph %>% filter(checks %in% ar_checks_4) %>% filter(ymin %in% ar_ymin) 

# Binary Marginal Effects and Prediction without Binary
st_title <- sprintf("BY FOUR Y GROUPS: Expected C without Binary Check and Marginal C Effects of Checks")
plt_A_alpha_grp <- dft_graph_subset %>% ggplot(aes(x=V_A_i)) +
      geom_point(aes(y=V_alpha_i,
                     color=factor(checks))) +
      geom_abline(intercept = 0, slope = 1) + # 45 degree line
      facet_wrap(~ ymin, nrow=2) +
      labs(title = st_title,
           subtitle = paste0(title_line1),
           x = st_x_label,
           y = st_y_label,
           caption = caption) 

# Labeling
plt_A_alpha_grp$labels$color <- "checks"

print(plt_A_alpha_grp)

f(A,alpha), color=age, panel=ymin

# Select 4 Y groups Levels
ar_age <- sort(unique(dft_graph %>% pull(age)))
ar_age <- ar_age[seq(1, 30, length.out=4)]
ar_ymin <- sort(unique(dft_graph %>% pull(ymin)))
ar_ymin <- ar_ymin[c(15, 20, 25, 30)]

dft_graph_subset <- dft_graph %>% 
  filter(ymin %in% ar_ymin) %>%
  filter(checks == 1) %>%
  filter(marital == 0) %>%
  filter(kids == 1)

# Binary Marginal Effects and Prediction without Binary
st_title <- sprintf("Color=Age, Panel=Y ; Married + 1 Kid + First Check")
plt_A_alpha_grp <- dft_graph_subset %>% ggplot(aes(x=A_i)) +
      geom_point(aes(y=alpha_i,
                     color=factor(age)), size=4) +
      geom_abline(intercept = 0, slope = 1) + # 45 degree line
      facet_wrap(~ ymin, nrow=2) +
      labs(title = st_title,
           subtitle = paste0(title_line1),
           x = st_x_label,
           y = st_y_label,
           caption = caption) 

# Labeling
plt_A_alpha_grp$labels$color <- "age"

print(plt_A_alpha_grp)

f(A,alpha), color=checks, panel=ymin

# Select 4 Y groups Levels
ar_checks <- sort(unique(tb_plan_v_tilde_a_alpha %>% pull(checks)))
ar_checks <- ar_checks[seq(1, length(ar_checks), length.out=4)]
ar_age <- sort(unique(dft_graph %>% pull(age)))
ar_age <- ar_age[seq(1, 30, length.out=4)]
ar_ymin <- sort(unique(dft_graph %>% pull(ymin)))
ar_ymin <- ar_ymin[c(30)]

dft_graph_subset <- dft_graph %>% 
  filter(ymin %in% ar_ymin) %>%
  filter(marital == 0) %>%
  filter(age == 50) %>%
  filter(kids %in% c(1))

# Binary Marginal Effects and Prediction without Binary
st_title <- sprintf("Color=Age, Panel=Y ; Married + 1 Kid + First Check")
plt_A_alpha_grp <- dft_graph_subset %>% ggplot(aes(x=A_i)) +
      geom_point(aes(y=alpha_i,
                     color=factor(checks)), size=4) +
      geom_abline(intercept = 0, slope = 1) + # 45 degree line
      facet_wrap(~ kids, nrow=2) +
      labs(title = st_title,
           subtitle = paste0(title_line1),
           x = st_x_label,
           y = st_y_label,
           caption = caption) 

# Labeling
plt_A_alpha_grp$labels$color <- "age"

print(plt_A_alpha_grp)

Value Summarize and Tabulate (Both Check no Check)

Aggregate Statistics:

REconTools::ff_summ_percentiles(tb_plan_v_tilde, bl_statsasrows = FALSE)
attributes are not identical across measure variables;
they will be dropped

Group Stats by Income

df <- tb_plan_v_tilde
vars.group <- c('ymin','age')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Age

df <- tb_plan_v_tilde
vars.group <- c('age')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Kids

df <- tb_plan_v_tilde
vars.group <- c('kids')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Marital Status

df <- tb_plan_v_tilde
vars.group <- c('marital')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Age and Marital Status

df <- tb_plan_v_tilde
vars.group <- c('age', 'marital')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Age and Marital Status and Kids

df <- tb_plan_v_tilde
vars.group <- c('age', 'marital', 'kids')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Summarize and Tabulate (Compare Check no Check)

Group Stats by Income and Checks

alpha statistics:

df <- tb_plan_v_tilde_a_alpha
vars.group <- c('ymin')
var.numeric <- 'alpha_i'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

A1 and A0 stats:

df <- tb_plan_v_tilde
vars.group <- c('ymin', 'checks')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Age and Checks

alpha statistics:

df <- tb_plan_v_tilde_a_alpha
vars.group <- c('age')
var.numeric <- 'alpha_i'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

A1 and A0 stats:

df <- tb_plan_v_tilde
vars.group <- c('age', 'checks')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Kids Checks

alpha statistics:

df <- tb_plan_v_tilde_a_alpha
vars.group <- c('kids')
var.numeric <- 'alpha_i'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

V with check and V without Check Statistics:

df <- tb_plan_v_tilde
vars.group <- c('kids', 'checks')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Marital Status and CHecks

alpha statistics:

df <- tb_plan_v_tilde_a_alpha
vars.group <- c('marital')
var.numeric <- 'alpha_i'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

A1 and A0 stats:

df <- tb_plan_v_tilde
vars.group <- c('marital', 'checks')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Age and Marital Status and CHecks

alpha statistics:

df <- tb_plan_v_tilde_a_alpha
vars.group <- c('age', 'marital' )
var.numeric <- 'alpha_i'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

A1 and A0 stats:

df <- tb_plan_v_tilde
vars.group <- c('age', 'marital', 'checks')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Marital Status and kids and CHecks

alpha statistics:

df <- tb_plan_v_tilde_a_alpha
vars.group <- c('marital', 'kids' )
var.numeric <- 'alpha_i'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

A1 and A0 stats:

df <- tb_plan_v_tilde
vars.group <- c('marital', 'kids', 'checks')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Group Stats by Age and Marital Status and Kids and Checks

alpha statistics:

df <- tb_plan_v_tilde_a_alpha
vars.group <- c('age', 'marital', 'kids')
var.numeric <- 'alpha_i'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

A1 and A0 stats:

df <- tb_plan_v_tilde
vars.group <- c('age', 'marital', 'kids', 'checks')
var.numeric <- 'vtilde'
str.stats.group <- 'allperc'
ar.perc <- c(0.05, 0.25, 0.5, 0.75, 0.95)
ls_summ_by_group <- REconTools::ff_summ_bygroup(df, vars.group, var.numeric, str.stats.group, ar.perc)
attributes are not identical across measure variables;
they will be dropped
ls_summ_by_group$df_table_grp_stats

Graphs

Graph Probability Mass

# select variables
tb_graph <- tb_plan_v_tilde %>% 
  select(mass, age, marital, kids, checks) %>%
  mutate(marital = as.factor(marital),
         kids = as.factor(kids),
         checks = as.factor(checks))

# graph
lineplot <- tb_graph %>%
  group_by(checks, age, marital, kids) %>%
  summarise(mean_mass = sum(mass)) %>%
  gather(variable, value, -checks, -age, -marital, -kids) %>%
  ggplot(aes(x=age, y=value,
             colour=checks, linetype=checks, shape=checks)) +
  facet_wrap( ~ marital + kids, nrow=2) +
  geom_line() +
  geom_point() +
  labs(title = paste0('Mass at States'),
       x = 'Age',
       y = 'Mass',
       caption = 'SVW 2020')
`summarise()` regrouping output by 'checks', 'age', 'marital' (override with `.groups` argument)
# graph
print(lineplot)

Graph Value Statistics By Various Statistics

# select variables
tb_graph <- tb_plan_v_tilde %>% 
  select(vtilde, age, mass, marital, kids, checks) %>%
  mutate(marital = as.factor(marital),
         kids = as.factor(kids),
         checks = as.factor(checks))

# graph
lineplot <- tb_graph %>%
  group_by(checks, age, marital, kids) %>%
  summarise(mean_vtilde = mean(vtilde*(mass/sum(mass)))) %>%
  gather(variable, value, -checks, -age, -marital, -kids) %>%
  ggplot(aes(x=age, y=value,
             colour=checks, linetype=checks, shape=checks)) +
  facet_wrap( ~ marital + kids, nrow=2) +
  geom_line() +
  geom_point() +
  labs(title = paste0('Planner Value by Checks'),
       x = 'Age',
       y = 'Planner Exp Value',
       caption = 'SVW 2020')
`summarise()` regrouping output by 'checks', 'age', 'marital' (override with `.groups` argument)
# graph
print(lineplot)

LS0tDQp0aXRsZTogIlRoaXMgZmlsZSBBbmFseXNpemVzIHRoZSBWYWx1ZSBGdW5jdGlvbiBvZiB0aGUgUGxhbm5lciBmcm9tIFNpbXVsYXRlZCBSZXN1bHRzIg0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD04KQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoUkVjb25Ub29scykNCmBgYA0KDQojIEFuYWx5emUgUGxhbm5lciBWYWx1ZQ0KDQojIyBJbXBvcnQgRGF0YQ0KDQpgYGB7cn0NCm10X3BsYW5fdl90aWxkZSA8LSByZWFkLmNzdignQzovVXNlcnMvZmFuL0RvY3VtZW50cy9Ecm9wYm94IChVSC1FQ09OKS9QcmpOeWdhYXJkU29yZW5zZW5XYW5nL091dHB1dC9zbnd4X3ZfcGxhbm5lcl9zbWFsbC5jc3YnLCBoZWFkZXI9RkFMU0UpDQphcl9zdF92YXJuYW1lcyA8LSBjKCdhZ2UnLCAnbWFyaXRhbCcsICdraWRzJywgJ2NoZWNrcycsCSd5bWluJywgJ3ltYXgnLCAnbWFzcycsICdzdXJ2aXZlJywgJ3Z0aWxkZScsICdjdGlsZGUnKQ0KdGJfcGxhbl92X3RpbGRlIDwtIGFzX3RpYmJsZShtdF9wbGFuX3ZfdGlsZGUpICU+JQ0KICByZW5hbWVfYWxsKH5jKGFyX3N0X3Zhcm5hbWVzKSkgJT4lDQogIHJvd2lkX3RvX2NvbHVtbih2YXIgPSAiaWQiKSAlPiUNCiAgZmlsdGVyKHZ0aWxkZSAhPSAwKQ0KDQojIENvbHVtbiAxOiBBZ2UgKGluIHllYXIgYmVmb3JlIENPVklEKQ0KIyBDb2x1bW4gMjogTWFyaXRhbCBzdGF0dXMgKDAgaWYgbm90IG1hcnJpZWQ7IDEgaWYgbWFycmllZCkNCiMgQ29sdW1uIDM6IE5yIG9mIGtpZHMgKDAsIDEsIC4uLiwgNSkgd2hlcmUgNSBtZWFucyA1IG9yIG1vcmUNCiMgQ29sdW1uIDQ6IE51bWJlciBvZiB3ZWxmYXJlIGNoZWNrcyAoaGVyZSBlaXRoZXIgZXF1YWwgdG8gMCBvciAxKQ0KIyBDb2x1bW4gNSBhbmQgY29sdW1uIDYgZ2l2ZSBpbmNvbWUgcmFuZ2UNCiMgU28gdGhlIGluZGl2aWR1YWwncyBpbmNvbWUgaXMgYXQgbGVhc3QgYXMgbGFyZ2UgYXMgdGhlIHZhbHVlIGluIGNvbHVtbiA1IGJ1dCBzdHJpY3RseSBsZXNzIHRoYW4gdGhlIHZhbHVlIGluIGNvbHVtbiA2DQojIENvbHVtbiA3OiBQb3B1bGF0aW9uIHdlaWdodCBPZiB0aGF0IHBhcnRpY3VsYXIgZ3JvdXAgKGluIHRoZSBzdGF0aW9uYXJ5IGRpc3RyaWJ1dGlvbikNCiMgQ29sdW1uIDg6IFN1cnZpdmFsIHByb2JhYmlsaXR5IG9mIHRoYXQgcGFydGljdWxhciBhZ2UgKHNpbmNlIHRoZSBwbGFubmVyIGtub3dzIHRoYXQgc29tZSBvZiB0aGUgaW5kaXZpZHVhbHMgd2lsbCBkaWUgYmVmb3JlIG5leHQgcGVyaW9kLCBzbyB3YXNuJ3Qgc3VyZSBob3cgeW91IHdhbnRlZCBtZSB0byBpbmNsdWRlIHRoYXQuIEkgZGlkIG5vdCBhbHJlYWR5IGluY2x1ZGUgaXQgaW4gVl50aWxkZSkNCiMgQ29sdW1uIDk6IFZhbHVlIG9mIHBsYW5uZXIgYXMgaW4gdGhlIHNsaWRlcyAod2l0aCB0aGUgZXhjZXB0aW9uIHRoYXQgSSBkaWRuJ3QgbXVsdGlwbHkgYnkgdGhlIHN1cnZpdmFsIHByb2JhYmlsaXR5DQpgYGANCg0KIyMgR2VuZXJhdGUgQSBhbmQgYWxwaGEgZmlsZSB2ZXJzaW9uDQoNCmBgYHtyfQ0KdGJfcGxhbl92X3RpbGRlX2FfYWxwaGEgPC0gdGJfcGxhbl92X3RpbGRlICU+JSANCiAgYXJyYW5nZShhZ2UsIG1hcml0YWwsIGtpZHMsIHltaW4sIGNoZWNrcywgdnRpbGRlLCBjdGlsZGUpICU+JQ0KICBncm91cF9ieShhZ2UsIG1hcml0YWwsIGtpZHMsIHltaW4pICU+JQ0KICBtdXRhdGUodnRpbGRlX2xlYWQgPSBsZWFkKHZ0aWxkZSksIA0KICAgICAgICAgY3RpbGRlX2xlYWQgPSBsZWFkKGN0aWxkZSkpICU+JQ0KICBmaWx0ZXIoY2hlY2tzICE9IG1heCh0Yl9wbGFuX3ZfdGlsZGUkY2hlY2tzKSkgJT4lDQogIHJlbmFtZShWX0FfaSA9IHZ0aWxkZSwgQ19BX2kgPSBjdGlsZGUpICU+JQ0KICBtdXRhdGUoVl9hbHBoYV9pID0gdnRpbGRlX2xlYWQgLSBWX0FfaSwgDQogICAgICAgICBDX2FscGhhX2kgPSBjdGlsZGVfbGVhZCAtIENfQV9pKSAlPiUNCiAgbXV0YXRlKGNoZWNrcyA9IGNoZWNrcyArIDEpICU+JQ0KICB1bmdyb3VwKCkNCnByaW50KHRiX3BsYW5fdl90aWxkZV9hX2FscGhhKQ0KYGBgDQoNCiMjIyMgU3VtbWFyaXplIEFsbCBDb2x1bW5zIFVuY29uZGl0aW9uYWwNCg0KYGBge3J9DQpSRWNvblRvb2xzOjpmZl9zdW1tX3BlcmNlbnRpbGVzKHRiX3BsYW5fdl90aWxkZV9hX2FscGhhLCBibF9zdGF0c2Fzcm93cyA9IEZBTFNFKQ0KYGBgDQoNCiMjIyMgU3VtbWFyaXplIEFsbCBDb2x1bW5zIGJ5IENoZWNrcw0KDQpXaWxsIHN1bW1hcml6ZSBhbGwgdmFyYWlibGVzIGJ5IDQgZGlmZmVyZW50IGNoZWNrIGFtb3VudHMsIHRoZSBmb3VyIGNoZWNrIGluY3JlbWVudHMgYXJlIChlYWNoIGlzIHdvcnRoIDIwMCBkb2xsYXJzKToNCg0KYGBge3J9DQojIFVuaXF1ZSBDaGVja3M6DQphcl9jaGVja3MgPC0gc29ydCh1bmlxdWUodGJfcGxhbl92X3RpbGRlX2FfYWxwaGEgJT4lIHB1bGwoY2hlY2tzKSkpDQphcl9jaGVja3NfNCA8LSBhcl9jaGVja3Nbc2VxKDEsIGxlbmd0aChhcl9jaGVja3MpLCBsZW5ndGgub3V0PTQpXQ0KbXRfY2hlY2tzXzQgPC0gYXJfY2hlY2tzXzQNCmRpbShtdF9jaGVja3NfNCkgPC0gYyhsZW5ndGgoYXJfY2hlY2tzXzQpLCAxKQ0KbXRfY2hlY2tzKjIwMA0KYGBgDQoNCk5vdyBzdW1tYXJpemUgYnkgdGhlc2UgY2hlY2sgYW1vdW50czoNCg0KYGBge3J9DQojIFN1bW1hcml6ZSBhbGwgVmFyaWFibGVzIEVhY2ggQ2hlY2s6DQpsc19zdGF0c19ieV9jaGVja3MgPSBzdXBwcmVzc1dhcm5pbmdzKA0KICBhcHBseShtdF9jaGVja3NfNCwgMSwNCiAgICAgICAgZnVuY3Rpb24ocm93KSB7DQogICAgICAgICAgZmxfY2hlY2sgPSByb3dbMV0NCiAgICAgICAgICBSRWNvblRvb2xzOjpmZl9zdW1tX3BlcmNlbnRpbGVzKA0KICAgICAgICAgICAgdGJfcGxhbl92X3RpbGRlX2FfYWxwaGEgJT4lIA0KICAgICAgICAgICAgICBmaWx0ZXIoY2hlY2tzID09IGZsX2NoZWNrKSwgDQogICAgICAgICAgICBibF9zdGF0c2Fzcm93cyA9IEZBTFNFKQ0KICAgICAgICB9KSkNCg0KIyBQcmludCBTdGF0cw0KcHJpbnQobHNfc3RhdHNfYnlfY2hlY2tzKQ0KYGBgDQoNCiMjIyMgSm9pbnQgZGlzdHJpYnV0aW9uIG9mIEEgYW5kIGFscGhhIGJ5IENoZWNrIChTaG93IE9ubHkgZm9yIEZvdXIgQ2hlY2tzKQ0KDQojIyMjIyBKb2ludCBEaXN0cmlidXRpb24gb2YgRWZmZWN0cyBvbiBDb25zdW1wdGlvbiANCg0KYGBge3J9DQojIEdlbmVyYXRlIEdhcCBWYXJpYWJsZQ0KZGZ0X2dyYXBoIDwtIHRiX3BsYW5fdl90aWxkZV9hX2FscGhhICU+JQ0KICBmaWx0ZXIoY2hlY2tzICVpbiUgYXJfY2hlY2tzXzQpICU+JQ0KICBtdXRhdGUobWFyaXRhbCA9IGFzLmZhY3RvcihtYXJpdGFsKSwNCiAgICAgICAgIGtpZHMgPSBhcy5mYWN0b3Ioa2lkcykpDQoNCiMgVGl0bGluZw0Kc3RfdGl0bGUgPC0gc3ByaW50ZigiMjAyMCBDb25zdW1wdGlvbiB3aXRob3V0IEJpbmFyeSBDaGVjayBhbmQgTWFyZ2luYWwgRWZmZWN0cyBvZiBDaGVja3MiKQ0KdGl0bGVfbGluZTEgPC0gc3ByaW50ZigiRWFjaCBjaXJjbGUgKGNyb3NzKSByZXByZXNlbnRzIGFuIEFnZS9NYXJyaWFnZS9DaGlsZC9JbmNvbWUvQ2hlY2sgVHlwZSIpDQp0aXRsZSA8LSBleHByZXNzaW9uKCdUaGUgam9pbnQgZGlzdHJpYnV0aW9uIG9mJ35BW2ldfidhbmQnfmFscGhhW2ldficsIENoZWNrcywgU05XIDIwMjAnKQ0KY2FwdGlvbiA8LSBwYXN0ZTAoJ0xpZmUgQ3ljbGUgU2ltdWxhdGlvbi4nKQ0KIyBMYWJlbHMNCnN0X3hfbGFiZWwgPC0gZXhwcmVzc2lvbignQ29ucyAyMDIwIHdpdGhvdXQgdGhlIE5leHQgSW5jcmVtZW50IG9mIENoZWNrcycpDQpzdF95X2xhYmVsIDwtIGV4cHJlc3Npb24oJ01hcmdpbmFsIEMgZnJvbSBBbiBBZGRpdGlvbmFsIENoZWNrJykNCg0KIyBCaW5hcnkgTWFyZ2luYWwgRWZmZWN0cyBhbmQgUHJlZGljdGlvbiB3aXRob3V0IEJpbmFyeQ0KcGx0X0FfYWxwaGEgPC0gZGZ0X2dyYXBoICU+JSBnZ3Bsb3QoYWVzKHg9Q19BX2kpKSArDQogICAgICBnZW9tX3BvaW50KGFlcyh5PUNfYWxwaGFfaSwNCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yPWZhY3RvcihjaGVja3MpKSkgKw0KICAgICAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArICMgNDUgZGVncmVlIGxpbmUNCiAgICAgIGxhYnModGl0bGUgPSBzdF90aXRsZSwNCiAgICAgICAgICAgc3VidGl0bGUgPSBwYXN0ZTAodGl0bGVfbGluZTEpLA0KICAgICAgICAgICB4ID0gc3RfeF9sYWJlbCwNCiAgICAgICAgICAgeSA9IHN0X3lfbGFiZWwsDQogICAgICAgICAgIGNhcHRpb24gPSBjYXB0aW9uKSANCiMgTGFiZWxpbmcNCnBsdF9BX2FscGhhJGxhYmVscyRjb2xvciA8LSAiY2hlY2tzIg0KDQpwcmludChwbHRfQV9hbHBoYSkNCmBgYA0KDQojIyMjIyBKb2ludCBEaXN0cmlidXRpb24gb2YgRWZmZWN0cyBvbiBWYWx1ZSANCg0KYGBge3J9DQojIEdlbmVyYXRlIEdhcCBWYXJpYWJsZQ0KZGZ0X2dyYXBoIDwtIHRiX3BsYW5fdl90aWxkZV9hX2FscGhhICU+JQ0KICBmaWx0ZXIoY2hlY2tzICVpbiUgYXJfY2hlY2tzXzQpICU+JQ0KICBtdXRhdGUobWFyaXRhbCA9IGFzLmZhY3RvcihtYXJpdGFsKSwNCiAgICAgICAgIGtpZHMgPSBhcy5mYWN0b3Ioa2lkcykpDQoNCiMgVGl0bGluZw0Kc3RfdGl0bGUgPC0gc3ByaW50ZigiVmFsdWUgKExpZmUtVGltZSkgd2l0aG91dCBCaW5hcnkgQ2hlY2sgYW5kIE1hcmdpbmFsIEVmZmVjdHMgb2YgQ2hlY2tzIikNCnRpdGxlX2xpbmUxIDwtIHNwcmludGYoIkVhY2ggY2lyY2xlIChjcm9zcykgcmVwcmVzZW50cyBhbiBBZ2UvTWFycmlhZ2UvQ2hpbGQvSW5jb21lL0NoZWNrIFR5cGUiKQ0KdGl0bGUgPC0gZXhwcmVzc2lvbignVGhlIGpvaW50IGRpc3RyaWJ1dGlvbiBvZid+QVtpXX4nYW5kJ35hbHBoYVtpXX4nLCBDaGVja3MsIFNOVyAyMDIwJykNCmNhcHRpb24gPC0gcGFzdGUwKCdMaWZlIEN5Y2xlIFNpbXVsYXRpb24uJykNCiMgTGFiZWxzDQpzdF94X2xhYmVsIDwtIGV4cHJlc3Npb24oJ0xpZmUtdGltZSBVdGlsaXR5IHdpdGhvdXQgdGhlIE5leHQgSW5jcmVtZW50IG9mIENoZWNrcycpDQpzdF95X2xhYmVsIDwtIGV4cHJlc3Npb24oJ01hcmdpbmFsIFYgZnJvbSBBbiBBZGRpdGlvbmFsIENoZWNrJykNCg0KIyBCaW5hcnkgTWFyZ2luYWwgRWZmZWN0cyBhbmQgUHJlZGljdGlvbiB3aXRob3V0IEJpbmFyeQ0KcGx0X0FfYWxwaGEgPC0gZGZ0X2dyYXBoICU+JSBnZ3Bsb3QoYWVzKHg9Vl9BX2kpKSArDQogICAgICBnZW9tX3BvaW50KGFlcyh5PVZfYWxwaGFfaSwNCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yPWZhY3RvcihjaGVja3MpKSkgKw0KICAgICAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArICMgNDUgZGVncmVlIGxpbmUNCiAgICAgIGxhYnModGl0bGUgPSBzdF90aXRsZSwNCiAgICAgICAgICAgc3VidGl0bGUgPSBwYXN0ZTAodGl0bGVfbGluZTEpLA0KICAgICAgICAgICB4ID0gc3RfeF9sYWJlbCwNCiAgICAgICAgICAgeSA9IHN0X3lfbGFiZWwsDQogICAgICAgICAgIGNhcHRpb24gPSBjYXB0aW9uKSANCiMgTGFiZWxpbmcNCnBsdF9BX2FscGhhJGxhYmVscyRjb2xvciA8LSAiY2hlY2tzIg0KDQpwcmludChwbHRfQV9hbHBoYSkNCmBgYA0KDQojIyMjIEpvaW50IGRpc3RyaWJ1dGlvbiBvZiBBIGFuZCBhbHBoYSBieSBJbmNvbWUgR3JvdXBzDQoNCmBgYHtyfQ0KIyBTZWxlY3QgNCBZIGdyb3VwcyBMZXZlbHMNCmFyX3ltaW4gPC0gc29ydCh1bmlxdWUodGJfcGxhbl92X3RpbGRlX2FfYWxwaGEgJT4lIHB1bGwoeW1pbikpKQ0KYXJfeW1pbiA8LSBhcl95bWluW3NlcSgxLCBsZW5ndGgoYXJfeW1pbiksIGxlbmd0aC5vdXQ9NCldDQoNCmRmdF9ncmFwaF9zdWJzZXQgPC0gZGZ0X2dyYXBoICU+JSBmaWx0ZXIoY2hlY2tzICVpbiUgYXJfY2hlY2tzXzQpICU+JSBmaWx0ZXIoeW1pbiAlaW4lIGFyX3ltaW4pIA0KDQojIEJpbmFyeSBNYXJnaW5hbCBFZmZlY3RzIGFuZCBQcmVkaWN0aW9uIHdpdGhvdXQgQmluYXJ5DQpzdF90aXRsZSA8LSBzcHJpbnRmKCJCWSBGT1VSIFkgR1JPVVBTOiBFeHBlY3RlZCBDIHdpdGhvdXQgQmluYXJ5IENoZWNrIGFuZCBNYXJnaW5hbCBDIEVmZmVjdHMgb2YgQ2hlY2tzIikNCnBsdF9BX2FscGhhX2dycCA8LSBkZnRfZ3JhcGhfc3Vic2V0ICU+JSBnZ3Bsb3QoYWVzKHg9Vl9BX2kpKSArDQogICAgICBnZW9tX3BvaW50KGFlcyh5PVZfYWxwaGFfaSwNCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yPWZhY3RvcihjaGVja3MpKSkgKw0KICAgICAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArICMgNDUgZGVncmVlIGxpbmUNCiAgICAgIGZhY2V0X3dyYXAofiB5bWluLCBucm93PTIpICsNCiAgICAgIGxhYnModGl0bGUgPSBzdF90aXRsZSwNCiAgICAgICAgICAgc3VidGl0bGUgPSBwYXN0ZTAodGl0bGVfbGluZTEpLA0KICAgICAgICAgICB4ID0gc3RfeF9sYWJlbCwNCiAgICAgICAgICAgeSA9IHN0X3lfbGFiZWwsDQogICAgICAgICAgIGNhcHRpb24gPSBjYXB0aW9uKSANCg0KIyBMYWJlbGluZw0KcGx0X0FfYWxwaGFfZ3JwJGxhYmVscyRjb2xvciA8LSAiY2hlY2tzIg0KDQpwcmludChwbHRfQV9hbHBoYV9ncnApDQpgYGANCg0KIyMjIyBmKEEsYWxwaGEpLCBjb2xvcj1hZ2UsIHBhbmVsPXltaW4NCg0KYGBge3J9DQojIFNlbGVjdCA0IFkgZ3JvdXBzIExldmVscw0KYXJfYWdlIDwtIHNvcnQodW5pcXVlKGRmdF9ncmFwaCAlPiUgcHVsbChhZ2UpKSkNCmFyX2FnZSA8LSBhcl9hZ2Vbc2VxKDEsIDMwLCBsZW5ndGgub3V0PTQpXQ0KYXJfeW1pbiA8LSBzb3J0KHVuaXF1ZShkZnRfZ3JhcGggJT4lIHB1bGwoeW1pbikpKQ0KYXJfeW1pbiA8LSBhcl95bWluW2MoMTUsIDIwLCAyNSwgMzApXQ0KDQpkZnRfZ3JhcGhfc3Vic2V0IDwtIGRmdF9ncmFwaCAlPiUgDQogIGZpbHRlcih5bWluICVpbiUgYXJfeW1pbikgJT4lDQogIGZpbHRlcihjaGVja3MgPT0gMSkgJT4lDQogIGZpbHRlcihtYXJpdGFsID09IDApICU+JQ0KICBmaWx0ZXIoa2lkcyA9PSAxKQ0KDQojIEJpbmFyeSBNYXJnaW5hbCBFZmZlY3RzIGFuZCBQcmVkaWN0aW9uIHdpdGhvdXQgQmluYXJ5DQpzdF90aXRsZSA8LSBzcHJpbnRmKCJDb2xvcj1BZ2UsIFBhbmVsPVkgOyBNYXJyaWVkICsgMSBLaWQgKyBGaXJzdCBDaGVjayIpDQpwbHRfQV9hbHBoYV9ncnAgPC0gZGZ0X2dyYXBoX3N1YnNldCAlPiUgZ2dwbG90KGFlcyh4PUFfaSkpICsNCiAgICAgIGdlb21fcG9pbnQoYWVzKHk9YWxwaGFfaSwNCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yPWZhY3RvcihhZ2UpKSwgc2l6ZT00KSArDQogICAgICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsgIyA0NSBkZWdyZWUgbGluZQ0KICAgICAgZmFjZXRfd3JhcCh+IHltaW4sIG5yb3c9MikgKw0KICAgICAgbGFicyh0aXRsZSA9IHN0X3RpdGxlLA0KICAgICAgICAgICBzdWJ0aXRsZSA9IHBhc3RlMCh0aXRsZV9saW5lMSksDQogICAgICAgICAgIHggPSBzdF94X2xhYmVsLA0KICAgICAgICAgICB5ID0gc3RfeV9sYWJlbCwNCiAgICAgICAgICAgY2FwdGlvbiA9IGNhcHRpb24pIA0KDQojIExhYmVsaW5nDQpwbHRfQV9hbHBoYV9ncnAkbGFiZWxzJGNvbG9yIDwtICJhZ2UiDQoNCnByaW50KHBsdF9BX2FscGhhX2dycCkNCmBgYA0KDQojIyMjIGYoQSxhbHBoYSksIGNvbG9yPWNoZWNrcywgcGFuZWw9eW1pbg0KDQpgYGB7cn0NCiMgU2VsZWN0IDQgWSBncm91cHMgTGV2ZWxzDQphcl9jaGVja3MgPC0gc29ydCh1bmlxdWUodGJfcGxhbl92X3RpbGRlX2FfYWxwaGEgJT4lIHB1bGwoY2hlY2tzKSkpDQphcl9jaGVja3MgPC0gYXJfY2hlY2tzW3NlcSgxLCBsZW5ndGgoYXJfY2hlY2tzKSwgbGVuZ3RoLm91dD00KV0NCmFyX2FnZSA8LSBzb3J0KHVuaXF1ZShkZnRfZ3JhcGggJT4lIHB1bGwoYWdlKSkpDQphcl9hZ2UgPC0gYXJfYWdlW3NlcSgxLCAzMCwgbGVuZ3RoLm91dD00KV0NCmFyX3ltaW4gPC0gc29ydCh1bmlxdWUoZGZ0X2dyYXBoICU+JSBwdWxsKHltaW4pKSkNCmFyX3ltaW4gPC0gYXJfeW1pbltjKDMwKV0NCg0KZGZ0X2dyYXBoX3N1YnNldCA8LSBkZnRfZ3JhcGggJT4lIA0KICBmaWx0ZXIoeW1pbiAlaW4lIGFyX3ltaW4pICU+JQ0KICBmaWx0ZXIobWFyaXRhbCA9PSAwKSAlPiUNCiAgZmlsdGVyKGFnZSA9PSA1MCkgJT4lDQogIGZpbHRlcihraWRzICVpbiUgYygxKSkNCg0KIyBCaW5hcnkgTWFyZ2luYWwgRWZmZWN0cyBhbmQgUHJlZGljdGlvbiB3aXRob3V0IEJpbmFyeQ0Kc3RfdGl0bGUgPC0gc3ByaW50ZigiQ29sb3I9QWdlLCBQYW5lbD1ZIDsgTWFycmllZCArIDEgS2lkICsgRmlyc3QgQ2hlY2siKQ0KcGx0X0FfYWxwaGFfZ3JwIDwtIGRmdF9ncmFwaF9zdWJzZXQgJT4lIGdncGxvdChhZXMoeD1BX2kpKSArDQogICAgICBnZW9tX3BvaW50KGFlcyh5PWFscGhhX2ksDQogICAgICAgICAgICAgICAgICAgICBjb2xvcj1mYWN0b3IoY2hlY2tzKSksIHNpemU9NCkgKw0KICAgICAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArICMgNDUgZGVncmVlIGxpbmUNCiAgICAgIGZhY2V0X3dyYXAofiBraWRzLCBucm93PTIpICsNCiAgICAgIGxhYnModGl0bGUgPSBzdF90aXRsZSwNCiAgICAgICAgICAgc3VidGl0bGUgPSBwYXN0ZTAodGl0bGVfbGluZTEpLA0KICAgICAgICAgICB4ID0gc3RfeF9sYWJlbCwNCiAgICAgICAgICAgeSA9IHN0X3lfbGFiZWwsDQogICAgICAgICAgIGNhcHRpb24gPSBjYXB0aW9uKSANCg0KIyBMYWJlbGluZw0KcGx0X0FfYWxwaGFfZ3JwJGxhYmVscyRjb2xvciA8LSAiYWdlIg0KDQpwcmludChwbHRfQV9hbHBoYV9ncnApDQpgYGANCiMjIFZhbHVlIFN1bW1hcml6ZSBhbmQgVGFidWxhdGUgKEJvdGggQ2hlY2sgbm8gQ2hlY2spDQoNCkFnZ3JlZ2F0ZSBTdGF0aXN0aWNzOg0KDQpgYGB7cn0NClJFY29uVG9vbHM6OmZmX3N1bW1fcGVyY2VudGlsZXModGJfcGxhbl92X3RpbGRlLCBibF9zdGF0c2Fzcm93cyA9IEZBTFNFKQ0KYGBgDQoNCiMjIyBHcm91cCBTdGF0cyBieSBJbmNvbWUgDQoNCmBgYHtyfQ0KZGYgPC0gdGJfcGxhbl92X3RpbGRlDQp2YXJzLmdyb3VwIDwtIGMoJ3ltaW4nLCdhZ2UnKQ0KdmFyLm51bWVyaWMgPC0gJ3Z0aWxkZScNCnN0ci5zdGF0cy5ncm91cCA8LSAnYWxscGVyYycNCmFyLnBlcmMgPC0gYygwLjA1LCAwLjI1LCAwLjUsIDAuNzUsIDAuOTUpDQpsc19zdW1tX2J5X2dyb3VwIDwtIFJFY29uVG9vbHM6OmZmX3N1bW1fYnlncm91cChkZiwgdmFycy5ncm91cCwgdmFyLm51bWVyaWMsIHN0ci5zdGF0cy5ncm91cCwgYXIucGVyYykNCmxzX3N1bW1fYnlfZ3JvdXAkZGZfdGFibGVfZ3JwX3N0YXRzDQpgYGANCg0KIyMjIEdyb3VwIFN0YXRzIGJ5IEFnZSANCg0KYGBge3J9DQpkZiA8LSB0Yl9wbGFuX3ZfdGlsZGUNCnZhcnMuZ3JvdXAgPC0gYygnYWdlJykNCnZhci5udW1lcmljIDwtICd2dGlsZGUnDQpzdHIuc3RhdHMuZ3JvdXAgPC0gJ2FsbHBlcmMnDQphci5wZXJjIDwtIGMoMC4wNSwgMC4yNSwgMC41LCAwLjc1LCAwLjk1KQ0KbHNfc3VtbV9ieV9ncm91cCA8LSBSRWNvblRvb2xzOjpmZl9zdW1tX2J5Z3JvdXAoZGYsIHZhcnMuZ3JvdXAsIHZhci5udW1lcmljLCBzdHIuc3RhdHMuZ3JvdXAsIGFyLnBlcmMpDQpsc19zdW1tX2J5X2dyb3VwJGRmX3RhYmxlX2dycF9zdGF0cw0KYGBgDQoNCiMjIyBHcm91cCBTdGF0cyBieSBLaWRzDQoNCmBgYHtyfQ0KZGYgPC0gdGJfcGxhbl92X3RpbGRlDQp2YXJzLmdyb3VwIDwtIGMoJ2tpZHMnKQ0KdmFyLm51bWVyaWMgPC0gJ3Z0aWxkZScNCnN0ci5zdGF0cy5ncm91cCA8LSAnYWxscGVyYycNCmFyLnBlcmMgPC0gYygwLjA1LCAwLjI1LCAwLjUsIDAuNzUsIDAuOTUpDQpsc19zdW1tX2J5X2dyb3VwIDwtIFJFY29uVG9vbHM6OmZmX3N1bW1fYnlncm91cChkZiwgdmFycy5ncm91cCwgdmFyLm51bWVyaWMsIHN0ci5zdGF0cy5ncm91cCwgYXIucGVyYykNCmxzX3N1bW1fYnlfZ3JvdXAkZGZfdGFibGVfZ3JwX3N0YXRzDQpgYGANCg0KIyMjIEdyb3VwIFN0YXRzIGJ5IE1hcml0YWwgU3RhdHVzDQoNCg0KYGBge3J9DQpkZiA8LSB0Yl9wbGFuX3ZfdGlsZGUNCnZhcnMuZ3JvdXAgPC0gYygnbWFyaXRhbCcpDQp2YXIubnVtZXJpYyA8LSAndnRpbGRlJw0Kc3RyLnN0YXRzLmdyb3VwIDwtICdhbGxwZXJjJw0KYXIucGVyYyA8LSBjKDAuMDUsIDAuMjUsIDAuNSwgMC43NSwgMC45NSkNCmxzX3N1bW1fYnlfZ3JvdXAgPC0gUkVjb25Ub29sczo6ZmZfc3VtbV9ieWdyb3VwKGRmLCB2YXJzLmdyb3VwLCB2YXIubnVtZXJpYywgc3RyLnN0YXRzLmdyb3VwLCBhci5wZXJjKQ0KbHNfc3VtbV9ieV9ncm91cCRkZl90YWJsZV9ncnBfc3RhdHMNCmBgYA0KIyMjIEdyb3VwIFN0YXRzIGJ5IEFnZSBhbmQgTWFyaXRhbCBTdGF0dXMNCg0KYGBge3J9DQpkZiA8LSB0Yl9wbGFuX3ZfdGlsZGUNCnZhcnMuZ3JvdXAgPC0gYygnYWdlJywgJ21hcml0YWwnKQ0KdmFyLm51bWVyaWMgPC0gJ3Z0aWxkZScNCnN0ci5zdGF0cy5ncm91cCA8LSAnYWxscGVyYycNCmFyLnBlcmMgPC0gYygwLjA1LCAwLjI1LCAwLjUsIDAuNzUsIDAuOTUpDQpsc19zdW1tX2J5X2dyb3VwIDwtIFJFY29uVG9vbHM6OmZmX3N1bW1fYnlncm91cChkZiwgdmFycy5ncm91cCwgdmFyLm51bWVyaWMsIHN0ci5zdGF0cy5ncm91cCwgYXIucGVyYykNCmxzX3N1bW1fYnlfZ3JvdXAkZGZfdGFibGVfZ3JwX3N0YXRzDQpgYGANCg0KIyMjIEdyb3VwIFN0YXRzIGJ5IEFnZSBhbmQgTWFyaXRhbCBTdGF0dXMgYW5kIEtpZHMNCg0KYGBge3J9DQpkZiA8LSB0Yl9wbGFuX3ZfdGlsZGUNCnZhcnMuZ3JvdXAgPC0gYygnYWdlJywgJ21hcml0YWwnLCAna2lkcycpDQp2YXIubnVtZXJpYyA8LSAndnRpbGRlJw0Kc3RyLnN0YXRzLmdyb3VwIDwtICdhbGxwZXJjJw0KYXIucGVyYyA8LSBjKDAuMDUsIDAuMjUsIDAuNSwgMC43NSwgMC45NSkNCmxzX3N1bW1fYnlfZ3JvdXAgPC0gUkVjb25Ub29sczo6ZmZfc3VtbV9ieWdyb3VwKGRmLCB2YXJzLmdyb3VwLCB2YXIubnVtZXJpYywgc3RyLnN0YXRzLmdyb3VwLCBhci5wZXJjKQ0KbHNfc3VtbV9ieV9ncm91cCRkZl90YWJsZV9ncnBfc3RhdHMNCmBgYA0KDQojIyBTdW1tYXJpemUgYW5kIFRhYnVsYXRlIChDb21wYXJlIENoZWNrIG5vIENoZWNrKQ0KDQojIyMgR3JvdXAgU3RhdHMgYnkgSW5jb21lIGFuZCBDaGVja3MNCg0KYWxwaGEgc3RhdGlzdGljczogDQoNCmBgYHtyfQ0KZGYgPC0gdGJfcGxhbl92X3RpbGRlX2FfYWxwaGENCnZhcnMuZ3JvdXAgPC0gYygneW1pbicpDQp2YXIubnVtZXJpYyA8LSAnYWxwaGFfaScNCnN0ci5zdGF0cy5ncm91cCA8LSAnYWxscGVyYycNCmFyLnBlcmMgPC0gYygwLjA1LCAwLjI1LCAwLjUsIDAuNzUsIDAuOTUpDQpsc19zdW1tX2J5X2dyb3VwIDwtIFJFY29uVG9vbHM6OmZmX3N1bW1fYnlncm91cChkZiwgdmFycy5ncm91cCwgdmFyLm51bWVyaWMsIHN0ci5zdGF0cy5ncm91cCwgYXIucGVyYykNCmxzX3N1bW1fYnlfZ3JvdXAkZGZfdGFibGVfZ3JwX3N0YXRzDQpgYGANCg0KQTEgYW5kIEEwIHN0YXRzOiANCg0KYGBge3J9DQpkZiA8LSB0Yl9wbGFuX3ZfdGlsZGUNCnZhcnMuZ3JvdXAgPC0gYygneW1pbicsICdjaGVja3MnKQ0KdmFyLm51bWVyaWMgPC0gJ3Z0aWxkZScNCnN0ci5zdGF0cy5ncm91cCA8LSAnYWxscGVyYycNCmFyLnBlcmMgPC0gYygwLjA1LCAwLjI1LCAwLjUsIDAuNzUsIDAuOTUpDQpsc19zdW1tX2J5X2dyb3VwIDwtIFJFY29uVG9vbHM6OmZmX3N1bW1fYnlncm91cChkZiwgdmFycy5ncm91cCwgdmFyLm51bWVyaWMsIHN0ci5zdGF0cy5ncm91cCwgYXIucGVyYykNCmxzX3N1bW1fYnlfZ3JvdXAkZGZfdGFibGVfZ3JwX3N0YXRzDQpgYGANCiMjIyBHcm91cCBTdGF0cyBieSBBZ2UgYW5kIENoZWNrcw0KDQphbHBoYSBzdGF0aXN0aWNzOiANCg0KYGBge3J9DQpkZiA8LSB0Yl9wbGFuX3ZfdGlsZGVfYV9hbHBoYQ0KdmFycy5ncm91cCA8LSBjKCdhZ2UnKQ0KdmFyLm51bWVyaWMgPC0gJ2FscGhhX2knDQpzdHIuc3RhdHMuZ3JvdXAgPC0gJ2FsbHBlcmMnDQphci5wZXJjIDwtIGMoMC4wNSwgMC4yNSwgMC41LCAwLjc1LCAwLjk1KQ0KbHNfc3VtbV9ieV9ncm91cCA8LSBSRWNvblRvb2xzOjpmZl9zdW1tX2J5Z3JvdXAoZGYsIHZhcnMuZ3JvdXAsIHZhci5udW1lcmljLCBzdHIuc3RhdHMuZ3JvdXAsIGFyLnBlcmMpDQpsc19zdW1tX2J5X2dyb3VwJGRmX3RhYmxlX2dycF9zdGF0cw0KYGBgDQoNCkExIGFuZCBBMCBzdGF0czogDQoNCmBgYHtyfQ0KZGYgPC0gdGJfcGxhbl92X3RpbGRlDQp2YXJzLmdyb3VwIDwtIGMoJ2FnZScsICdjaGVja3MnKQ0KdmFyLm51bWVyaWMgPC0gJ3Z0aWxkZScNCnN0ci5zdGF0cy5ncm91cCA8LSAnYWxscGVyYycNCmFyLnBlcmMgPC0gYygwLjA1LCAwLjI1LCAwLjUsIDAuNzUsIDAuOTUpDQpsc19zdW1tX2J5X2dyb3VwIDwtIFJFY29uVG9vbHM6OmZmX3N1bW1fYnlncm91cChkZiwgdmFycy5ncm91cCwgdmFyLm51bWVyaWMsIHN0ci5zdGF0cy5ncm91cCwgYXIucGVyYykNCmxzX3N1bW1fYnlfZ3JvdXAkZGZfdGFibGVfZ3JwX3N0YXRzDQpgYGANCg0KIyMjIEdyb3VwIFN0YXRzIGJ5IEtpZHMgQ2hlY2tzDQoNCmFscGhhIHN0YXRpc3RpY3M6IA0KDQpgYGB7cn0NCmRmIDwtIHRiX3BsYW5fdl90aWxkZV9hX2FscGhhDQp2YXJzLmdyb3VwIDwtIGMoJ2tpZHMnKQ0KdmFyLm51bWVyaWMgPC0gJ2FscGhhX2knDQpzdHIuc3RhdHMuZ3JvdXAgPC0gJ2FsbHBlcmMnDQphci5wZXJjIDwtIGMoMC4wNSwgMC4yNSwgMC41LCAwLjc1LCAwLjk1KQ0KbHNfc3VtbV9ieV9ncm91cCA8LSBSRWNvblRvb2xzOjpmZl9zdW1tX2J5Z3JvdXAoZGYsIHZhcnMuZ3JvdXAsIHZhci5udW1lcmljLCBzdHIuc3RhdHMuZ3JvdXAsIGFyLnBlcmMpDQpsc19zdW1tX2J5X2dyb3VwJGRmX3RhYmxlX2dycF9zdGF0cw0KYGBgDQoNClYgd2l0aCBjaGVjayBhbmQgViB3aXRob3V0IENoZWNrIFN0YXRpc3RpY3M6DQoNCmBgYHtyfQ0KZGYgPC0gdGJfcGxhbl92X3RpbGRlDQp2YXJzLmdyb3VwIDwtIGMoJ2tpZHMnLCAnY2hlY2tzJykNCnZhci5udW1lcmljIDwtICd2dGlsZGUnDQpzdHIuc3RhdHMuZ3JvdXAgPC0gJ2FsbHBlcmMnDQphci5wZXJjIDwtIGMoMC4wNSwgMC4yNSwgMC41LCAwLjc1LCAwLjk1KQ0KbHNfc3VtbV9ieV9ncm91cCA8LSBSRWNvblRvb2xzOjpmZl9zdW1tX2J5Z3JvdXAoZGYsIHZhcnMuZ3JvdXAsIHZhci5udW1lcmljLCBzdHIuc3RhdHMuZ3JvdXAsIGFyLnBlcmMpDQpsc19zdW1tX2J5X2dyb3VwJGRmX3RhYmxlX2dycF9zdGF0cw0KYGBgDQoNCiMjIyBHcm91cCBTdGF0cyBieSBNYXJpdGFsIFN0YXR1cyBhbmQgQ0hlY2tzDQoNCmFscGhhIHN0YXRpc3RpY3M6IA0KDQpgYGB7cn0NCmRmIDwtIHRiX3BsYW5fdl90aWxkZV9hX2FscGhhDQp2YXJzLmdyb3VwIDwtIGMoJ21hcml0YWwnKQ0KdmFyLm51bWVyaWMgPC0gJ2FscGhhX2knDQpzdHIuc3RhdHMuZ3JvdXAgPC0gJ2FsbHBlcmMnDQphci5wZXJjIDwtIGMoMC4wNSwgMC4yNSwgMC41LCAwLjc1LCAwLjk1KQ0KbHNfc3VtbV9ieV9ncm91cCA8LSBSRWNvblRvb2xzOjpmZl9zdW1tX2J5Z3JvdXAoZGYsIHZhcnMuZ3JvdXAsIHZhci5udW1lcmljLCBzdHIuc3RhdHMuZ3JvdXAsIGFyLnBlcmMpDQpsc19zdW1tX2J5X2dyb3VwJGRmX3RhYmxlX2dycF9zdGF0cw0KYGBgDQoNCkExIGFuZCBBMCBzdGF0czogDQoNCmBgYHtyfQ0KZGYgPC0gdGJfcGxhbl92X3RpbGRlDQp2YXJzLmdyb3VwIDwtIGMoJ21hcml0YWwnLCAnY2hlY2tzJykNCnZhci5udW1lcmljIDwtICd2dGlsZGUnDQpzdHIuc3RhdHMuZ3JvdXAgPC0gJ2FsbHBlcmMnDQphci5wZXJjIDwtIGMoMC4wNSwgMC4yNSwgMC41LCAwLjc1LCAwLjk1KQ0KbHNfc3VtbV9ieV9ncm91cCA8LSBSRWNvblRvb2xzOjpmZl9zdW1tX2J5Z3JvdXAoZGYsIHZhcnMuZ3JvdXAsIHZhci5udW1lcmljLCBzdHIuc3RhdHMuZ3JvdXAsIGFyLnBlcmMpDQpsc19zdW1tX2J5X2dyb3VwJGRmX3RhYmxlX2dycF9zdGF0cw0KYGBgDQoNCiMjIyBHcm91cCBTdGF0cyBieSBBZ2UgYW5kIE1hcml0YWwgU3RhdHVzIGFuZCBDSGVja3MNCg0KYWxwaGEgc3RhdGlzdGljczogDQoNCmBgYHtyfQ0KZGYgPC0gdGJfcGxhbl92X3RpbGRlX2FfYWxwaGENCnZhcnMuZ3JvdXAgPC0gYygnYWdlJywgJ21hcml0YWwnICkNCnZhci5udW1lcmljIDwtICdhbHBoYV9pJw0Kc3RyLnN0YXRzLmdyb3VwIDwtICdhbGxwZXJjJw0KYXIucGVyYyA8LSBjKDAuMDUsIDAuMjUsIDAuNSwgMC43NSwgMC45NSkNCmxzX3N1bW1fYnlfZ3JvdXAgPC0gUkVjb25Ub29sczo6ZmZfc3VtbV9ieWdyb3VwKGRmLCB2YXJzLmdyb3VwLCB2YXIubnVtZXJpYywgc3RyLnN0YXRzLmdyb3VwLCBhci5wZXJjKQ0KbHNfc3VtbV9ieV9ncm91cCRkZl90YWJsZV9ncnBfc3RhdHMNCmBgYA0KDQpBMSBhbmQgQTAgc3RhdHM6IA0KDQpgYGB7cn0NCmRmIDwtIHRiX3BsYW5fdl90aWxkZQ0KdmFycy5ncm91cCA8LSBjKCdhZ2UnLCAnbWFyaXRhbCcsICdjaGVja3MnKQ0KdmFyLm51bWVyaWMgPC0gJ3Z0aWxkZScNCnN0ci5zdGF0cy5ncm91cCA8LSAnYWxscGVyYycNCmFyLnBlcmMgPC0gYygwLjA1LCAwLjI1LCAwLjUsIDAuNzUsIDAuOTUpDQpsc19zdW1tX2J5X2dyb3VwIDwtIFJFY29uVG9vbHM6OmZmX3N1bW1fYnlncm91cChkZiwgdmFycy5ncm91cCwgdmFyLm51bWVyaWMsIHN0ci5zdGF0cy5ncm91cCwgYXIucGVyYykNCmxzX3N1bW1fYnlfZ3JvdXAkZGZfdGFibGVfZ3JwX3N0YXRzDQpgYGANCg0KIyMjIEdyb3VwIFN0YXRzIGJ5IE1hcml0YWwgU3RhdHVzIGFuZCBraWRzIGFuZCBDSGVja3MNCg0KYWxwaGEgc3RhdGlzdGljczogDQoNCmBgYHtyfQ0KZGYgPC0gdGJfcGxhbl92X3RpbGRlX2FfYWxwaGENCnZhcnMuZ3JvdXAgPC0gYygnbWFyaXRhbCcsICdraWRzJyApDQp2YXIubnVtZXJpYyA8LSAnYWxwaGFfaScNCnN0ci5zdGF0cy5ncm91cCA8LSAnYWxscGVyYycNCmFyLnBlcmMgPC0gYygwLjA1LCAwLjI1LCAwLjUsIDAuNzUsIDAuOTUpDQpsc19zdW1tX2J5X2dyb3VwIDwtIFJFY29uVG9vbHM6OmZmX3N1bW1fYnlncm91cChkZiwgdmFycy5ncm91cCwgdmFyLm51bWVyaWMsIHN0ci5zdGF0cy5ncm91cCwgYXIucGVyYykNCmxzX3N1bW1fYnlfZ3JvdXAkZGZfdGFibGVfZ3JwX3N0YXRzDQpgYGANCg0KQTEgYW5kIEEwIHN0YXRzOiANCg0KYGBge3J9DQpkZiA8LSB0Yl9wbGFuX3ZfdGlsZGUNCnZhcnMuZ3JvdXAgPC0gYygnbWFyaXRhbCcsICdraWRzJywgJ2NoZWNrcycpDQp2YXIubnVtZXJpYyA8LSAndnRpbGRlJw0Kc3RyLnN0YXRzLmdyb3VwIDwtICdhbGxwZXJjJw0KYXIucGVyYyA8LSBjKDAuMDUsIDAuMjUsIDAuNSwgMC43NSwgMC45NSkNCmxzX3N1bW1fYnlfZ3JvdXAgPC0gUkVjb25Ub29sczo6ZmZfc3VtbV9ieWdyb3VwKGRmLCB2YXJzLmdyb3VwLCB2YXIubnVtZXJpYywgc3RyLnN0YXRzLmdyb3VwLCBhci5wZXJjKQ0KbHNfc3VtbV9ieV9ncm91cCRkZl90YWJsZV9ncnBfc3RhdHMNCmBgYA0KDQoNCiMjIyBHcm91cCBTdGF0cyBieSBBZ2UgYW5kIE1hcml0YWwgU3RhdHVzIGFuZCBLaWRzIGFuZCBDaGVja3MNCg0KYWxwaGEgc3RhdGlzdGljczogDQoNCmBgYHtyfQ0KZGYgPC0gdGJfcGxhbl92X3RpbGRlX2FfYWxwaGENCnZhcnMuZ3JvdXAgPC0gYygnYWdlJywgJ21hcml0YWwnLCAna2lkcycpDQp2YXIubnVtZXJpYyA8LSAnYWxwaGFfaScNCnN0ci5zdGF0cy5ncm91cCA8LSAnYWxscGVyYycNCmFyLnBlcmMgPC0gYygwLjA1LCAwLjI1LCAwLjUsIDAuNzUsIDAuOTUpDQpsc19zdW1tX2J5X2dyb3VwIDwtIFJFY29uVG9vbHM6OmZmX3N1bW1fYnlncm91cChkZiwgdmFycy5ncm91cCwgdmFyLm51bWVyaWMsIHN0ci5zdGF0cy5ncm91cCwgYXIucGVyYykNCmxzX3N1bW1fYnlfZ3JvdXAkZGZfdGFibGVfZ3JwX3N0YXRzDQpgYGANCg0KQTEgYW5kIEEwIHN0YXRzOiANCg0KYGBge3J9DQpkZiA8LSB0Yl9wbGFuX3ZfdGlsZGUNCnZhcnMuZ3JvdXAgPC0gYygnYWdlJywgJ21hcml0YWwnLCAna2lkcycsICdjaGVja3MnKQ0KdmFyLm51bWVyaWMgPC0gJ3Z0aWxkZScNCnN0ci5zdGF0cy5ncm91cCA8LSAnYWxscGVyYycNCmFyLnBlcmMgPC0gYygwLjA1LCAwLjI1LCAwLjUsIDAuNzUsIDAuOTUpDQpsc19zdW1tX2J5X2dyb3VwIDwtIFJFY29uVG9vbHM6OmZmX3N1bW1fYnlncm91cChkZiwgdmFycy5ncm91cCwgdmFyLm51bWVyaWMsIHN0ci5zdGF0cy5ncm91cCwgYXIucGVyYykNCmxzX3N1bW1fYnlfZ3JvdXAkZGZfdGFibGVfZ3JwX3N0YXRzDQpgYGANCg0KIyMgR3JhcGhzDQoNCiMjIyBHcmFwaCBQcm9iYWJpbGl0eSBNYXNzIA0KDQpgYGB7cn0NCiMgc2VsZWN0IHZhcmlhYmxlcw0KdGJfZ3JhcGggPC0gdGJfcGxhbl92X3RpbGRlICU+JSANCiAgc2VsZWN0KG1hc3MsIGFnZSwgbWFyaXRhbCwga2lkcywgY2hlY2tzKSAlPiUNCiAgbXV0YXRlKG1hcml0YWwgPSBhcy5mYWN0b3IobWFyaXRhbCksDQogICAgICAgICBraWRzID0gYXMuZmFjdG9yKGtpZHMpLA0KICAgICAgICAgY2hlY2tzID0gYXMuZmFjdG9yKGNoZWNrcykpDQoNCiMgZ3JhcGgNCmxpbmVwbG90IDwtIHRiX2dyYXBoICU+JQ0KICBncm91cF9ieShjaGVja3MsIGFnZSwgbWFyaXRhbCwga2lkcykgJT4lDQogIHN1bW1hcmlzZShtZWFuX21hc3MgPSBzdW0obWFzcykpICU+JQ0KICBnYXRoZXIodmFyaWFibGUsIHZhbHVlLCAtY2hlY2tzLCAtYWdlLCAtbWFyaXRhbCwgLWtpZHMpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9YWdlLCB5PXZhbHVlLA0KICAgICAgICAgICAgIGNvbG91cj1jaGVja3MsIGxpbmV0eXBlPWNoZWNrcywgc2hhcGU9Y2hlY2tzKSkgKw0KICBmYWNldF93cmFwKCB+IG1hcml0YWwgKyBraWRzLCBucm93PTIpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBsYWJzKHRpdGxlID0gcGFzdGUwKCdNYXNzIGF0IFN0YXRlcycpLA0KICAgICAgIHggPSAnQWdlJywNCiAgICAgICB5ID0gJ01hc3MnLA0KICAgICAgIGNhcHRpb24gPSAnU1ZXIDIwMjAnKQ0KIyBncmFwaA0KcHJpbnQobGluZXBsb3QpDQoNCmBgYA0KDQojIyMgR3JhcGggVmFsdWUgU3RhdGlzdGljcyBCeSBWYXJpb3VzIFN0YXRpc3RpY3MNCg0KYGBge3J9DQojIHNlbGVjdCB2YXJpYWJsZXMNCnRiX2dyYXBoIDwtIHRiX3BsYW5fdl90aWxkZSAlPiUgDQogIHNlbGVjdCh2dGlsZGUsIGFnZSwgbWFzcywgbWFyaXRhbCwga2lkcywgY2hlY2tzKSAlPiUNCiAgbXV0YXRlKG1hcml0YWwgPSBhcy5mYWN0b3IobWFyaXRhbCksDQogICAgICAgICBraWRzID0gYXMuZmFjdG9yKGtpZHMpLA0KICAgICAgICAgY2hlY2tzID0gYXMuZmFjdG9yKGNoZWNrcykpDQoNCiMgZ3JhcGgNCmxpbmVwbG90IDwtIHRiX2dyYXBoICU+JQ0KICBncm91cF9ieShjaGVja3MsIGFnZSwgbWFyaXRhbCwga2lkcykgJT4lDQogIHN1bW1hcmlzZShtZWFuX3Z0aWxkZSA9IG1lYW4odnRpbGRlKihtYXNzL3N1bShtYXNzKSkpKSAlPiUNCiAgZ2F0aGVyKHZhcmlhYmxlLCB2YWx1ZSwgLWNoZWNrcywgLWFnZSwgLW1hcml0YWwsIC1raWRzKSAlPiUNCiAgZ2dwbG90KGFlcyh4PWFnZSwgeT12YWx1ZSwNCiAgICAgICAgICAgICBjb2xvdXI9Y2hlY2tzLCBsaW5ldHlwZT1jaGVja3MsIHNoYXBlPWNoZWNrcykpICsNCiAgZmFjZXRfd3JhcCggfiBtYXJpdGFsICsga2lkcywgbnJvdz0yKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgbGFicyh0aXRsZSA9IHBhc3RlMCgnUGxhbm5lciBWYWx1ZSBieSBDaGVja3MnKSwNCiAgICAgICB4ID0gJ0FnZScsDQogICAgICAgeSA9ICdQbGFubmVyIEV4cCBWYWx1ZScsDQogICAgICAgY2FwdGlvbiA9ICdTVlcgMjAyMCcpDQojIGdyYXBoDQpwcmludChsaW5lcGxvdCkNCg0KYGBgDQoNCg==